﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Data;
using System;
using System.Reflection;
using NetSystem;

namespace ResourceSystem
{
    public enum GameModeType
    {
        Debug=1,
        Release=2,
    }

    /// <summary>
    /// 资源管理
    /// </summary>
    public class ResourceSystemFacade : Singleton<ResourceSystemFacade>
    {
        public bool IsAB { get; private set; }

        public bool IsInit { get; private set; }

        public Dictionary<string, ResourcesData> ResDict = new Dictionary<string, ResourcesData>();

        public List<string> LoadedRes = new List<string>();

        public static string AbOutPath = Application.dataPath+"/../../Res/AssetBundles/Windows";

        public static string ConfigPath = Application.dataPath + "/../../Res/Config";

        public static string ResInfoConfigPath = Application.dataPath + "/Resources/Editor/ResInfo/";

        public static string GameSettingPath = ConfigPath + "/GameSetting.json";

        public static string ScriptableObjectResPath = Application.dataPath + "/Resources/ScriptableObject/";

        public static string FileExtension = "assetbundle";

        public static string Version="1.0.0.0";

        public static GameModeType GameMode;

        public Action OnSystemInitFinish;

        /// <summary>
        /// 下载队列
        /// </summary>
        public Queue<AssetBundleStream> DownLoadQueue = new Queue<AssetBundleStream>();

        public void InitSystem(bool isAb = true)
        {
            DisposeSystem();
            IsAB = isAb;
            LitJson.JsonData data = ResourceSystemFacade.Inst.ReadJson(ResourceSystemFacade.ConfigPath + "/GameSetting.json");
            Version = data["Version"].AsString;
            GameMode = (GameModeType)data["GameMode"].AsInt;
            if (isAb)
            {
                AssetBundleStream resInfoStream = LoadResourceFromABNotDependency("ResourcesInfo");
                resInfoStream.OnLoadFinish += () => {
                    ResourcesInfo info = (ResourcesInfo)resInfoStream.Bundle.LoadAsset("ResourcesInfo");
                    if (info!=null)
                    {
                        for (int i = 0; i < info.Data.Count; i++)
                        {
                            ResDict.Add(info.Data[i].Name, info.Data[i]);
                        }
                    }
                    else
                    {
                        DebugUtils.LogRedInfo("未取到当前版本号资源信息 " + Version);
                    }

                    IsInit = true;
                    DebugUtils.LogRedInfo("OnSystemInitFinish");
                    if (OnSystemInitFinish!=null)
                    {
                        OnSystemInitFinish();
                    }
                  
                };
            }else
            {
                ResourcesInfo info = Resources.Load<ResourcesInfo>("ScriptableObject/ResourcesInfo");
                Debug.Log(ScriptableObjectResPath + "ResourcesInfo"+(info ==null));
                for (int i = 0; i < info.Data.Count; i++)
                {
                    ResDict.Add(info.Data[i].Name, info.Data[i]);
                }
                if (OnSystemInitFinish != null)
                {
                    OnSystemInitFinish();
                }
            }
            OnSystemInitFinish = null;
        }

        public void DisposeSystem()
        {
            IsInit = false;
            ResDict.Clear();
        }

        #region 资源打包相关

        /// <summary>
        /// 版本号规则
        /// </summary>
        public void UpdateVersionToJson()
        {
            //尾数递增1
            string[] version = Version.Split('.');
            version[version.Length - 1] = (Int32.Parse(version[version.Length - 1]) + 1).ToString();
            for (int i = version.Length-1; i >=0; i--)
            {
                //逢10进1
                if (Int32.Parse( version[i])>= 10)
                {
                    if (i-1>=0)
                    {
                        version[i] = "0";
                        version[i - 1] = (Int32.Parse(version[i - 1]) + 1).ToString();
                    }
                    else
                    {
                        DebugUtils.LogError("超过版本号能容纳的极限");
                    }
                } 
            }
 
            Version = ConvertUtils.ConvertStringArrayToString(version,".");


            //写入Json
            LitJson.JsonData data = ReadJson(GameSettingPath);
            data["Version"] = Version;
            WriteJson(GameSettingPath,data);
        }

        public string GetPreviousVersion()
        {
            string[] version = Version.Split('.');
            int tempNum=0;
            for (int i = version.Length-1; i >=0; i--)
            {
                tempNum = Int32.Parse(version[i]);
                if (tempNum-1>=0)
                {
                    version[i] = (tempNum - 1).ToString();
                    break;
                }
                else
                {
                    version[i] = "9";
                }
            }

            string previousVersion = ConvertUtils.ConvertStringArrayToString(version, ".");
            return previousVersion;
        }

        #endregion

        #region Get

        public string GetTargetResIDByPath(string path)
        {
            return "";
        }

        public string GetTargetVersionByResID(string path)
        {
            return "";
        }

        #endregion

        #region Excel读写

        public void WriteToExcel(string path ,string sheetName,string[,] content)
        {
            ExcelStream stream = new ExcelStream();
            ExcelWriteArgs args = new ExcelWriteArgs();
            args.Path = path;
            args.SheetName = sheetName;
            args.Content = content;
            stream.WriteResource(args);
        }

        public List<IDataTemplete> ReadExcel(Type type,string path,int sheetIndex=0)
        {
            ConstructorInfo[] infos= type.GetConstructors();
            int index = -1;
            for(int i = 0; i < infos.Length; i++)
            {
                if (infos[i].GetParameters().Length == 0)
                {
                    index = i;
                }
            }
            List<IDataTemplete> data = new List<IDataTemplete>();
            if (index != -1)
            {
                ExcelStream stream = new ExcelStream();
                DataTableCollection collection = (DataTableCollection)stream.ReadResouce(path);
                for (int i = 3; i < collection[sheetIndex].Rows.Count; i++)
                {
                    IDataTemplete temp =(IDataTemplete)infos[index].Invoke(new object[] { });
                    temp.DeSerialize(collection[sheetIndex].Rows[i].ItemArray);
                    data.Add(temp);
                }
            }

            
            return data;
        }

        public DataTableCollection ReadExcel(string path) 
        {
            ExcelStream stream = new ExcelStream();
            return (DataTableCollection)stream.ReadResouce(path);
        }

        #endregion

        #region Json读写
        public LitJson.JsonData ReadJson(string path)
        {
            JsonStream stream = new JsonStream();
            return (LitJson.JsonData)stream.ReadResouce( path);
        }

        public void WriteJson(string path,LitJson.JsonData content)
        {
            JsonStream stream = new JsonStream();
            JsonWriteArgs args = new JsonWriteArgs();
            args.Path = path;
            args.Content = content;
            stream.WriteResource(args);
        }
        #endregion

        #region 资源加载

        public void DownLoadResourcesAndSave(string relativePath)
        {
            string path = NetSystemFacade.ResourceURL + "/" + relativePath+"."+ FileExtension;
            AssetBundleStream abStream = new AssetBundleStream();
            abStream.OnLoadFinish += () =>
            {
                AssetBundleWriteArgs args = new AssetBundleWriteArgs();
                args.Bytes = abStream.Bytes;
                args.Path = path;
                abStream.WriteResource(args);
            };
            abStream.ReadResouce(path);
        }

        /// <summary>
        /// 从文件名读取
        /// </summary>
        /// <param name="resName"></param>
        /// <returns></returns>
        public object LoadResource(string resName)
        {
            object resObj = null;
            if (ResDict.ContainsKey(resName))
            {
                resObj = Resources.Load(ResDict[resName].Path +"/"+ resName);
            }
            return resObj;
        }

        /// <summary>
        /// 从文件名读取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public T LoadResource<T>(string resName) where T: UnityEngine.Object
        {
            T resObj = default(T);
            if (ResDict.ContainsKey(resName))
            {
                resObj = Resources.Load<T>(ResDict[resName].Path + "/" + resName);
            }
            return resObj;
        }



        public AssetBundleStream LoadResourceFromABNotDependency(string resName, Action onLoadFinish = null)
        {
            AssetBundleStream abStream = new AssetBundleStream();
            abStream.OnLoadFinish += onLoadFinish;
            string path = NetSystemFacade.ResourceURL+ "Assetbundle/Windows/Release/" + Version + "/" + resName.ToLower() + "." + FileExtension;
            DebugUtils.LogRedInfo(path);
            abStream.ReadResouce(path);
            return abStream;
        }

        public AssetBundleStream LoadResourceFromAB(string resName, Action onLoadFinish = null)
        {
            AssetBundleStream abStream= new AssetBundleStream();
            abStream.OnLoadFinish += onLoadFinish;
           
            if (ResDict.ContainsKey(resName))
            {
                string path = NetSystemFacade.ResourceURL + "/"+  resName.ToLower()+"."+FileExtension;

                DebugUtils.LogRedInfo(path);

                for (int i = 0; i < ResDict[resName].Dependencys.Count; i++)
                {
                    AssetBundleStream abChildStream = LoadResourceFromAB(ResDict[resName].Dependencys[i]);
                    abChildStream.OnLoadFinish += () =>
                    {
                        bool isLoaded=true;
                        LoadedRes.Add(PathUtils.GetFileNameWithoutExtension(abChildStream.Bundle.name));
                        DebugUtils.LogRedInfo(abChildStream.Bundle.name);
                        for (int j = 0; j < ResDict[resName].Dependencys.Count; j++)
                        {
                            if (!LoadedRes.Contains(ResDict[resName].Dependencys[j]))
                            {
                                DebugUtils.LogRedInfo(ResDict[resName].Dependencys[j]);
                                isLoaded = false;
                            }
                        }

                        if (isLoaded)
                        {
                            abStream.ReadResouce(path);
                        }
                    };
                    string chidResName = ResDict[resName].Dependencys[i];
                    DebugUtils.LogRedInfo(chidResName);
                    if (ResDict.ContainsKey(chidResName))
                    {
                        string childPath = NetSystemFacade.ResourceURL + "/" + chidResName.ToLower()+"."+FileExtension;
                        abChildStream.ReadResouce(childPath);
                    }
                }
            }
            
            return abStream;
        }

        public AssetBundleStream DownLoadResource(string resName)
        {
            AssetBundleStream downStream = new AssetBundleStream();
            AssetBundleWriteArgs args = new AssetBundleWriteArgs();
            args.Path = NetSystemFacade.ResourceURL + "/" + resName.ToLower() + "." + FileExtension;
            downStream.WriteResource(args);
            return downStream;
        }

#endregion

        #region 卸载资源
        public bool UnLoadResource()
        {
            return true;
        }
        #endregion


    }
}